#导入了 requests 库，它是 Python 中常用的用于发送 HTTP 请求的库，能够方便地向网页服务器发起 GET、POST 等请求，并获取响应内容，
# 在代码中主要用于获取去哪儿网相关页面的 HTML 文本内容。
import requests
# 从 lxml 库中导入了 etree 模块，lxml 是一个功能强大的用于处理 XML 和 HTML 文档的 Python 库，etree 模块提供了便捷的方法来解析 HTML 文档，
# 构建元素树结构，便于通过 XPath 表达式提取网页中的特定元素信息，代码中利用它来解析获取到的网页内容，提取城市相关元素。
from lxml import etree
import csv
# 用于与操作系统进行交互，执行诸如文件和目录相关的操作，代码中主要利用它来判断本地是否已存在要保存数据的 CSV 文件，从而决定是否需要初始化创建该文件。
import os
# 用于初始化本地的 city.csv 文件。
def init():
    # 检查是否存在名为 city.csv 的文件，如果不存在，则创建该文件，并写入 CSV 文件的表头信息，
    # 即 ['city', 'cityLink']，分别代表城市名称和对应的景点门票列表页面链接，为后续写入具体的城市及链接数据做准备。
    if not os.path.exists('city.csv'):
        with open('city.csv','w',encoding='utf8',newline='') as csvfile:
            wirter = csv.writer(csvfile)
            wirter.writerow([
                'city',
                'cityLink'
            ])
# 用于初始化本地的 city.csv 文件。
def wirterRow(row):
        # 检查是否存在名为 city.csv 的文件，如果不存在，则创建该文件，并写入 CSV 文件的表头信息，即 ['city', 'cityLink']，
        # 分别代表城市名称和对应的景点门票列表页面链接，为后续写入具体的城市及链接数据做准备。
        with open('city.csv','a',encoding='utf8',newline='') as csvfile:
            wirter = csv.writer(csvfile)
            wirter.writerow(row)
# 根据传入的 URL 发送 HTTP GET 请求，尝试获取对应的网页内容。
def get_html(url):
    # 设置了请求头信息（headers），
    headers  = {
        # 模拟浏览器访问，其中包含了常见的 User-Agent（用于标识客户端信息，让服务器认为请求来自浏览器）以及一长串的 Cookie
        # （用于维持会话状态、绕过某些访问限制等，具体取决于去哪儿网的页面逻辑和反爬机制）。
        'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/117.0.0.0 Safari/537.36',
        'Cookie':'QN1=00006300306c49a231301a3f; QN300=s%3Dbaidu; '
                 'QN99=3425; QunarGlobal=10.67.197.57_-315863c_184a309bb38_-1d6c|1669185576668; '
                 'fid=d2274349-f1bd-4865-9f33-2d14799ef8d2; '
                 'ctt_june=1654604625968##iK3wVKjOVuPwawPwasPwaRDwaSvNXK2nEKfhVKPAas2NEKXmERgmX2jwESt%3DiK3siK3saKjOVKDmWKjnas2nWhPwaUvt; '
                 'QN57=16735024544680.884216181267804; QN271AC=register_pc; QN269=EC1BA1D02D0E11EEAE97FA163E6051F0; '
                 'QN205=s%3Dbaidu; QN48=tc_c37b032d4fcdcb6e_1899bb77459_488a; ariaDefaultTheme=null; '
                 'QN601=8fc403fedc30423ad9bf80560e31c026; '
                 'quinn=52cff7791fb2241bffb9f293396244b1195afeecb5ca4eae483d850d7b0c028d6a231e97613a2bcc4cf790cdd99dc6b7; '
                 'HN1=v1c4cacceff43bcaf2c3221e6ac091b5fa; HN2=qukzullckqssz; QN243=9; QN63=%E5%8C%97%E4%BA%AC; '
                 'ctf_june=1683616182042##iK3wWSPOWwPwawPwa%3DERaKaNEPWTXSg%3DaS2wWRvOW2ETX%3DjAaK0TaSkDa23NiK3siK3saKjNaRg%2BVKa%2BWSDmWuPwaUvt; cs_june=a2251d3540fc6e52d313a0280598ebce169fbeccf97b7783ac905a4cd61ca7917ddda68253ca261c13b71af11083b5969380af884f02ad66396ed55ce1f811ecb17c80df7eee7c02a9c1a6a5b97c11791cb994da421857cea53abba039d353d55a737ae180251ef5be23400b098dd8ca; QN271SL=3a947e0d87871ace6f5cf42f3ab6f46d; QN271RC=3a947e0d87871ace6f5cf42f3ab6f46d; _q=U.txsewnz1317; csrfToken=ntVx9eipihjmotqX9cYxuUlPokMkflGH; _s=s_BOMLYBFWFGV6OGKDQ5EGVTNLOU; _t=28289096; _v=F5QaIBiw16AiX4iIGFExpwiRaDxqr8WSlHIVZy73KI9vhAiqNUnMGIMqYgRN9robdTZ1sxYtdjvQZIM8jnZNPBYz3XkwP24OsGNtzWDarvX-FgJmDsA3errgxcQgj7JAllpWEF-nxbE9JIwry4oBbKKpN4iiHg3-6tU1HXKKfgH0; QN43=""; QN42=%E5%8E%BB%E5%93%AA%E5%84%BF%E7%94%A8%E6%88%B7; _i=DFiEuDr3m5674XSwtqKxYvshUjOw; QNSPU=2052539421%2C3320442612%2C127362640%2C721810477; QN277=s%3Dbaidu; QN71="MzYuMTU3LjIxOC4yODrljJfkuqw6MQ=="; qunar-assist={%22version%22:%2220211215173359.925%22%2C%22show%22:false%2C%22audio%22:false%2C%22speed%22:%22middle%22%2C%22zomm%22:1%2C%22cursor%22:false%2C%22pointer%22:false%2C%22bigtext%22:false%2C%22overead%22:false%2C%22readscreen%22:false%2C%22theme%22:%22default%22}; QN44=txsewnz1317; QN67=38170%2C507738%2C11824; Hm_lvt_15577700f8ecddb1a927813c81166ade=1690779361,1690784008,1690784225,1690870921; _vi=-k2AsGRKl8xEYYNxNyO4cVpTyqU0MRywS3aFzPMk1xU86S8RXFt5VEjW5-558kNFKPwUK-YuouGTcnnU9R8gIqPsftC_QO1WxhUuLWGhwzoDfNfNlJ8iAgvwM1xlAP8wYnKsSR2e4PpUrLr1WzQS5xj4TTixsTty74uli_TMs8lP; QN58=1690875915134%7C1690876060197%7C12; Hm_lpvt_15577700f8ecddb1a927813c81166ade=1690876061; QN271=50e3e9ff-99ab-41de-9b81-79b73691639b; JSESSIONID=A797207C02559CA92998EDB64DB63821; QN267=01574179237f0e556bd; __qt=v1%7CVTJGc2RHVmtYMTlaTE8rRXVESTdwNTVPN3F5N0ovNi9iZUxxdmhxUW5wOUo3OWFyQ3BUSGhIN3VGenNRMFBDRy9zSGFaZ2VpSkpwVXhYTzlyckpTVUN5anFlajZYQWZzOU1TK1JCOXlBVE1IdTZUTi9BU1ltaFY0ZFFLOUpCczdLRTRyYzdFM0VjWHhrdXBlajBzRTNpemJjdnErWHJmNWFGNmxFSXpJdU5RPQ%3D%3D%7C1690876265736%7CVTJGc2RHVmtYMTlQSU43VW94SzhTYU1RcGI5ZDhteHM2bXVVSVZ4cnI4RFZwRTZNSExZMS9pMDJOUE0zQS9rRjhpbUJsQzEyVnZYcFR4anVIeHJxS0E9PQ%3D%3D%7CVTJGc2RHVmtYMTlBeXZ0dG56UlRuRU9HVG5rSVhwcXl0cEU2SkcvclJwaGVkRjhoUXZzeS9VaW5HaCtCWmxEd0hBemJCQW5ENHl5SFJXdVJwaVdkWVJ3c2NUK1NCWDRkMHJRM2MycytsWi9MZ0gwSk5YckJ1T3A3dHZnZngrT3B0ekg1ZHErcnVXZHl0SVFRcnJDVmJabFVsdjUzaklPR016TUFrWFRNbm5jc3RsSVJTenRiSHV6WEpsMWYzcFZFUjFCMU1OMDI3NEN1RnM4RkM1Y3JDeUQ0SWVDMUVuT2dnKzlMR3JBQS93Vm5yd0YwTzJWWjlCWlFmSTV3cXlZVEJUTUxxYXg5RUo4MzRWQnZmcDl4UnhKZC9MckJxSndZcUlHMDRlbnF6OGZST2t0aGwwYk1UOUorTitNWGdGaitRNUJ6d3BmN0JwZGVCV0FjSVZnWmNyWWgzYkRpcCtnQkZnT3VNZkd4UG95SW95ajN4bzJMSWpTUmR0RTR5UkZIdkZkVjBnTDBITTBxcTh1K1Erbk1vS0IwdzhTUi9Nako3VDYzTHl2aCtnT0U0NjBOUVJyZXRaUVJmckQrWnl0ODd1WWhjdVdFaGRRZzQxSjh6ZHJjWkJkWEQ0M0dUb3JrbTBad3BmVGlndTY5TnN6Q25lMGxqV05WdjdocEtMMHlnSlNQbVVTOStXUks1aFNaREpGN1ZmSk5IMk5NVEtDVFcwNnlMbmVuNitUODQxTkFTWUlMNEpwY0d1Q1A3UlBocTIzRnNDZzl1OGpjc2pDc1BjU1ZOSCsxTFNsZ1p1T2toeTJLZDh2SXlRVi8zVEx3bWtTM3BhUi8rOFhNN1JVbEl3MUdNbUd6dzYzVWZ6K3BleW1Ca1RVbTdLeDBhck1mQUJleFM0VWQ0TjlzZk1WN3hrRmdZMGJrSU1JalpMNW96ZDBQbDhxN2M5MW5iUnkxUVV1eHgyVERKak9WM2tZWE1taXl4ZHdBenhKa1lKQ0x5by9lYk5yemo4RGo3dmRn'
    }
    response = requests.get(url,headers=headers)
    # 如果请求成功（状态码为 200），则返回对应的 response 对象，包含了获取到的网页文本内容等信息；
    if response.status_code == 200:
        return response
    # 若请求失败（状态码非 200），则返回 None，表示获取网页内容失败。
    else:
        return None
# 解析传入的 response 对象（包含网页内容），提取出城市名称以及对应的景点门票列表页面链接，并将这些信息逐行写入到 city.csv 文件中。
def parse_html(response):
    # 首先通过 etree.HTML 将网页文本内容解析为可操作的元素树结构，
    root = etree.HTML(response.text)
    # 然后通过 XPath 表达式 //div[@class="mp-city-content"]//li[@class="mp-city-item"]/a
    # 来定位页面中表示城市信息的 <a> 标签元素列表（每个元素对应一个城市），
    cityList = root.xpath('//div[@class="mp-city-content"]//li[@class="mp-city-item"]/a')
    # 接着遍历这个列表，
    for city in cityList:
        # 获取每个城市元素中的文本作为城市名称（cityName），并根据城市名称拼接出对应的景点门票列表页面链接（cityLink），
        cityName = city.text
        cityLink = 'https://piao.qunar.com/ticket/list.htm?keyword=%s' % cityName
        # 最后调用 wirterRow 函数将城市名称和链接组成的列表数据写入到 CSV 文件中。
        wirterRow([
            cityName,
            cityLink
        ])
# 这是整个程序的入口部分。
if __name__ == '__main__':
    # 首先定义了要抓取的网页 URL（去哪儿网一日游列表页面），
    url = 'https://piao.qunar.com/daytrip/list.htm'
    # 然后调用 init 函数初始化 CSV 文件，
    init()
    # 接着调用 get_html 函数发送请求获取网页响应内容，如果请求成功得到响应，再将响应传递给 parse_html 函数进行页面解析及数据提取
    # 和存储到 CSV 文件的操作。
    response = get_html(url)
    parse_html(response)